﻿using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FRMS.WebSockets
{
    public class WebSocketMiddleware
    {
        public static List<WebSocket> _sockets = new List<WebSocket>();
        private readonly RequestDelegate _next;
        public WebSocketMiddleware(RequestDelegate next)
        {
            this._next = next;
            // this._manage = manage;
        }
        public async Task Invoke(HttpContext context)
        {
            WebSocket currentSocket = null;
            try
            {
                if (!context.WebSockets.IsWebSocketRequest)
                {
                    await _next.Invoke(context);
                    return;
                }
                CancellationToken cancellationToken = context.RequestAborted;
                currentSocket = await context.WebSockets.AcceptWebSocketAsync();
                _sockets.Add(currentSocket);
                while (!currentSocket.CloseStatus.HasValue)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                    string response = await ReceiveStringAsync(currentSocket, cancellationToken);
                    if (response != null)
                    {
                    }

                }
                if (currentSocket != null && currentSocket.CloseStatus != null)
                    await currentSocket.CloseAsync(currentSocket.CloseStatus.Value, currentSocket.CloseStatusDescription, CancellationToken.None);
            }
            catch (Exception e)
            {
                _sockets.Remove(currentSocket);
            }
        }
        public static async Task<string> ReceiveStringAsync(WebSocket socket, CancellationToken ct)
        {
            var buffer = new ArraySegment<byte>(new byte[4 * 1024]);
            using (var ms = new MemoryStream())
            {
                WebSocketReceiveResult result;
                do
                {
                    ct.ThrowIfCancellationRequested();
                    try
                    {
                        result = await socket.ReceiveAsync(buffer, ct);
                        ms.Write(buffer.Array, buffer.Offset, result.Count);
                    }
                    catch (Exception e) { return null; }
                }
                while (!result.EndOfMessage);
                ms.Seek(0, SeekOrigin.Begin);
                if (result.MessageType != WebSocketMessageType.Text)
                {
                    return null;
                }
                using (var reader = new StreamReader(ms, Encoding.UTF8))
                {
                    return await reader.ReadToEndAsync();
                }
            }
        }

        public static void RemoveSocket(WebSocket webSocket)
        {
            _sockets.Remove(webSocket);
        }
    }
}
